import { reactive, InjectionKey, ref } from 'vue'
import {
  IDesignerIconStore,
  IDesignerAppTheme,
  IDesignerAppConfig,
  IDesignerLocales,
  IDesignerBehaviorStore,
  IBehaviorLike,
  IBehavior,
} from './types'

import { isBehaviorHost, isBehaviorList } from './externals'
import { Path } from '@formily/path'
import { observable } from '@formily/reactive'
import { TreeNode } from './models'
import { mergeLocales, lowerSnake, getBrowserLanguage } from './internals'
import { each } from '@/shared'

export const DESIGNER_LAYOUT_SYMBOL: InjectionKey<IDesignerAppConfig> = Symbol(
  'DESIGNER_LAYOUT_SYMBOL',
)
// 全局默认配置
const DESIGNER_APP_CONFIG = reactive<IDesignerAppConfig>({
  appTheme: 'light',
  prefixCls: 'dn-',
  fontColor: '#6c848d',
  iconTheme: 'multi-color',
  followSystem: false,
  iconFill: '#000',
  iconSize: 18,
  strokeWidth: 4,
  strokeLinecap: 'round',
  strokeLinejoin: 'round',
  rtl: false,
  iconColor: {
    outline: {
      fill: '#333',
      background: 'transparent',
    },
    filled: {
      fill: '#333',
      background: '#FFF',
    },
    twoTone: {
      fill: '#333',
      twoTone: '#2F88FF',
    },
    multiColor: {
      outStrokeColor: '#333',
      outFillColor: '#2F88FF',
      innerStrokeColor: '#FFF',
      innerFillColor: '#43CCF8',
    },
  },
})
const DESIGNER_BEHAVIORS_STORE: IDesignerBehaviorStore = observable.ref([])

const DESIGNER_LOCALES_STORE: IDesignerLocales = reactive({})

const DESIGNER_ICONS_STORE: IDesignerIconStore = {}

const DESIGNER_LANGUAGE_STORE = ref(getBrowserLanguage())

const getISOCode = (language: string) => {
  let isoCode = DESIGNER_LANGUAGE_STORE.value
  let lang = lowerSnake(language)
  if (DESIGNER_LOCALES_STORE[lang]) {
    return lang
  }
  each(DESIGNER_LOCALES_STORE, (_: any, key: string) => {
    if (key.indexOf(lang) > -1 || String(lang).indexOf(key) > -1) {
      isoCode = key
      return false
    }
  })
  return isoCode
}

const DESIGNER_Global_Registry = {
  getDesignerAppConfig: () => {
    return DESIGNER_APP_CONFIG
  },

  setDesignerLayout: (value: IDesignerAppTheme) => {
    DESIGNER_APP_CONFIG.appTheme = value
  },

  registerDesignerIcons: (map: IDesignerIconStore) => {
    Object.assign(DESIGNER_ICONS_STORE, map)
  },

  getDesignerIcon: (name: string) => {
    return DESIGNER_ICONS_STORE[name]
  },

  registerDesignerLocales: (...packages: IDesignerLocales[]) => {
    packages.forEach((locales) => {
      mergeLocales(DESIGNER_LOCALES_STORE, locales)
    })
  },

  getDesignerMessage: (token: string, locales?: IDesignerLocales) => {
    const lang = getISOCode(DESIGNER_LANGUAGE_STORE.value)
    const locale = locales ? locales[lang] : DESIGNER_LOCALES_STORE[lang]
    if (!locale) {
      for (let key in DESIGNER_LOCALES_STORE) {
        const message = Path.getIn(
          DESIGNER_LOCALES_STORE[key],
          lowerSnake(token),
        )
        if (message) return message
      }
      return
    }
    return Path.getIn(locale, lowerSnake(token))
  },

  setDesignerLanguage: (lang: string) => {
    DESIGNER_LANGUAGE_STORE.value = lang
  },

  getDesignerLanguage: (): string => {
    return getISOCode(DESIGNER_LANGUAGE_STORE.value)
  },

  setDesignerBehaviors: (behaviors: IBehaviorLike[]) => {
    DESIGNER_BEHAVIORS_STORE.value = behaviors.reduce<IBehavior[]>(
      (buf, behavior) => {
        if (isBehaviorHost(behavior)) {
          return buf.concat(behavior.Behavior)
        } else if (isBehaviorList(behavior)) {
          return buf.concat(behavior)
        }
        return buf
      },
      [],
    )
  },

  getDesignerBehaviors: (node: TreeNode) => {
    return DESIGNER_BEHAVIORS_STORE.value.filter((pattern) =>
      pattern.selector(node),
    )
  },
}

export type IDesignerRegistry = typeof DESIGNER_Global_Registry

export const GlobalRegistry: IDesignerRegistry =
  (window as any)['__DESIGNER_GlobalRegistry__'] || DESIGNER_Global_Registry
